# -*- coding: utf-8 -*-
"""
国网 /meter/+/telemetry 统一入口
"""
from __future__ import annotations

import paho.mqtt.client as mqtt

from common.config import settings
from common.database import DatabaseManager
from common.logger import create_logger
from mqtt.consumer.alarm_worker import AlarmWorker
from mqtt.consumer.rule_engine import RuleEngine
from mqtt.consumer.transform_layer import process as _transform

logger = create_logger("mqtt_handler", settings.log_level, settings.log_file)


class TelemetryHandler:
	INSERT_TEL = """
        INSERT IGNORE INTO dc_meter_telemetry
          (msg_id, meter_code, phase, ts, voltage, current, watt, total_kwh,
           temperature1, temperature2, quality, ext_json)
        VALUES (%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s)
    """

	def __init__(self, db: DatabaseManager) -> None:
		self.db = db
		self.engine = RuleEngine(db)
		self.alarm_worker = AlarmWorker(db, self.engine)  # 后续可替换为 MQ 生产者

	# ---------------- 入口 ----------------
	def handle(self, topic: str, payload: str) -> None:
		try:
			rows, event = _transform(payload.encode(), topic, self.db)
		except Exception as e:
			logger.warning("报文转换失败 topic=%s %s", topic, e)
			# 增加原始数据日志，帮助调试
			logger.debug("原始 payload 内容: %s", payload[:1000] if len(payload) > 1000 else payload)
			return
		if not rows:
			logger.debug("转换后 0 行，直接返回")
			return

		# 1. 落库（带 quality）
		with self.db.transaction():
			self._save_telemetry(rows)
		logger.info("telemetry 入库完成 msg_id=%s rows=%d", rows[0].msg_id, len(rows))

		# 2. 把事件交给下游（现在是本地调用，后续可改 MQ）
		self.alarm_worker.on_event(event)

	# ---------------- private ----------------
	def _save_telemetry(self, rows: list) -> None:
		args = [r.to_db_tuple() for r in rows]
		affected = self.db.executemany(self.INSERT_TEL, args)
		logger.debug("telemetry affected=%d", affected)


# ---------------------------------------------------------------------------
# 工厂 & 默认兜底
# ---------------------------------------------------------------------------
class HandlerFactory:
	@staticmethod
	def get_handler(topic: str, db: DatabaseManager):
		"""
		根据topic选择handler
		
		注意：每个节点只订阅自己的topic，只连接自己的数据库
		- Worker节点: 订阅 /meter/+/telemetry，使用 .env.test 配置
		- Worker-Show节点: 订阅 /meter/+/telemetry/qz，使用 .env.show 配置
		
		Args:
			topic: MQTT主题
			db: 数据库连接
			
		Returns:
			对应的Handler实例
		"""
		# 匹配所有telemetry相关topic
		if mqtt.topic_matches_sub("/meter/+/telemetry", topic) or \
				mqtt.topic_matches_sub("/meter/+/telemetry/qz", topic):
			return TelemetryHandler(db)
		# 未匹配到任何pattern
		return DefaultHandler(db)


class DefaultHandler:
	"""未匹配主题时兜底"""

	def __init__(self, db: DatabaseManager | None = None) -> None:
		self.db = db  # 预留扩展

	def handle(self, topic: str, payload: str) -> None:
		logger.warning("无处理器 topic=%s payload_len=%d", topic, len(payload))
